package com.szcinda.fitness;

import com.szcinda.fitness.dto.DailyTrainDto;
import com.szcinda.fitness.dto.TrainPlanDto;
import com.szcinda.fitness.persistence.BodyMeasurement;
import com.szcinda.fitness.persistence.DailyTrain;
import com.szcinda.fitness.persistence.TrainMovement;
import com.szcinda.fitness.persistence.TrainPlan;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@Service
@Transactional
public class TrainServiceImpl implements TrainService {

    private final TrainPlanRepository trainPlanRepository;
    private final DailyTrainRepository dailyTrainRepository;
    private final SnowFlakeFactory snowFlakeFactory;

    public TrainServiceImpl(TrainPlanRepository trainPlanRepository, DailyTrainRepository dailyTrainRepository) {
        this.trainPlanRepository = trainPlanRepository;
        this.dailyTrainRepository = dailyTrainRepository;
        snowFlakeFactory = SnowFlakeFactory.getInstance();
    }

    @Override
    public DailyTrainDto getDailyTrain(String openId, LocalDate trainDate) {
        DailyTrain dailyTrain = dailyTrainRepository.findByOpenIdAndTrainDate(openId, trainDate);
        DailyTrainDto trainDto = new DailyTrainDto();
        if (dailyTrain != null) {
            BeanUtils.copyProperties(dailyTrain, trainDto);
            trainDto.convertPositions(dailyTrain.getTrainPositions());
            trainDto.convertTypes(dailyTrain.getTrainTypes());
        }
        return trainDto;
    }

    @Override
    public TrainPlanDto getTrainPlan(String openId) {
        TrainPlan trainPlan = trainPlanRepository.findByOpenId(openId);
        TrainPlanDto dto = new TrainPlanDto();
        if (trainPlan != null) {
            BeanUtils.copyProperties(trainPlan, dto);
            dto.convertDemand(trainPlan.getTrainDemand());
        }
        return dto;
    }

    @Override
    public List<String> trainDayList(String openId) {
        List<LocalDate> trainDays = dailyTrainRepository.findTrainDayRecords(openId);
        List<String> trainDayRecords = new ArrayList<>();
        LocalDate today = LocalDate.now();
        String todayString = today.toString();
        if (trainDays.size() > 0) {
            trainDays.forEach(item -> trainDayRecords.add(item.toString()));
        }
        if (!trainDayRecords.contains(todayString)) {
            trainDayRecords.add(todayString);
        }
        return trainDayRecords;
    }

    @Override
    public void saveTrainPlan(TrainPlan trainPlan) {
        Assert.notNull(trainPlan.getOpenId(), "学员不能为空");
        TrainPlan existTrainPlan = trainPlanRepository.findByOpenId(trainPlan.getOpenId());
        if (existTrainPlan == null) {
            trainPlanRepository.save(trainPlan);
        } else {
            existTrainPlan.setTrainDemand(trainPlan.getTrainDemand());
            existTrainPlan.setRemark(trainPlan.getRemark());
            trainPlanRepository.save(existTrainPlan);
        }
    }

    @Override
    public void saveNote(String openId, LocalDate trainDate, String trainNote) {
        Assert.notNull(openId, "学员OPENID不能为空");
        Assert.notNull(trainDate, "日期不能为空");
        DailyTrain dailyTrain = findDailyTrain(openId, trainDate);
        dailyTrain.setTrainNote(trainNote);
        dailyTrainRepository.save(dailyTrain);
    }

    private void checkNotNull(String openId, LocalDate trainDate){
        Assert.notNull(openId, "学员OPENID不能为空");
        Assert.notNull(trainDate, "日期不能为空");
    }

    @Override
    public void saveTrainPositions(String openId, LocalDate trainDate, String trainPositions) {
        checkNotNull(openId,trainDate);
        DailyTrain dailyTrain = findDailyTrain(openId, trainDate);
        dailyTrain.setTrainPositions(trainPositions);
        dailyTrainRepository.save(dailyTrain);
    }

    @Override
    public void saveTrainTypes(String openId, LocalDate trainDate, String trainTypes) {
        checkNotNull(openId,trainDate);
        DailyTrain dailyTrain = findDailyTrain(openId, trainDate);
        dailyTrain.setTrainTypes(trainTypes);
        dailyTrainRepository.save(dailyTrain);
    }

    @Override
    public void saveTrainMovements(String openId, LocalDate trainDate, List<TrainMovement> trainMovements) {
        checkNotNull(openId,trainDate);
        DailyTrain dailyTrain = findDailyTrain(openId, trainDate);
        trainMovements.forEach(item -> item.setId(snowFlakeFactory.nextId()));
        dailyTrain.addMovements(trainMovements);
        dailyTrainRepository.save(dailyTrain);
    }

    @Override
    public void saveBodyMeasurements(String openId, LocalDate trainDate, List<BodyMeasurement> bodyMeasurements) {
        checkNotNull(openId,trainDate);
        DailyTrain dailyTrain = findDailyTrain(openId, trainDate);
        bodyMeasurements.removeIf(item->item.getValue()<=0);
        bodyMeasurements.forEach(item -> item.setId(snowFlakeFactory.nextId()));
        dailyTrain.setBodyMeasurements(bodyMeasurements);
        dailyTrainRepository.save(dailyTrain);
    }

    private DailyTrain findDailyTrain(String openId, LocalDate trainDate) {
        DailyTrain dailyTrain = dailyTrainRepository.findByOpenIdAndTrainDate(openId, trainDate);
        if (dailyTrain == null) {
            dailyTrain = new DailyTrain();
            dailyTrain.setId(snowFlakeFactory.nextId());
            dailyTrain.setOpenId(openId);
            dailyTrain.setTrainDate(trainDate);
        }
        return dailyTrain;
    }
}
